package daisy;

import grafico.GerenteGUI;

import java.util.List;
import java.util.ArrayList;

//import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


public class EstruturaXML extends EstruturaBase 
{
	private int ordem;
	private List<RegParteTexto> lstSentencas;
	
	public EstruturaXML()
	{
		setNomeArquivo(null);
		
		lstSentencas = new ArrayList<RegParteTexto>();
	}

	public List<RegParteTexto> getLstSentencas()		{ return lstSentencas;			}
	public void setLstSentencas(List<RegParteTexto> l)	{ lstSentencas = l;				}
	public int getNumSentencas()						{ return lstSentencas.size();	}

	public RegParteTexto getSentenca(int p)				
	{
		if ( p < lstSentencas.size() )
			return lstSentencas.get(p);
		
		return null;
	}
	
	public RegParteTexto getSentenca(String id)			
	{
		for ( int i = 0; i < lstSentencas.size(); i++ )
			if ( lstSentencas.get(i).getId().equals(id) )
				return lstSentencas.get(i);
		
		return null;	
	}
	
	public boolean estaCarregado(String nome)
	{
		return (nomeArquivo != null) && (nomeArquivo.equals(nome));
	}

	public boolean abrir( String nomeArq )
	{
		setNomeArquivo(null);

		if ( !parseFile(nomeArq) )
			return false;

		if ( !montaListaTexto() )
			return false;

		setNomeArquivo(nomeArq);

		return true;
	}

	// retorna todos os textos filhos de um no 
	public String extraiTexto( Node no )
	{
		String paragrafo;
		NodeList lisFilhos;
		
		if ( no == null )
			return "";

		paragrafo = "";
		lisFilhos = no.getChildNodes();
		if ( lisFilhos != null && lisFilhos.getLength() > 0 ) 
		{
			Node noFilho;
			
			for( int i = 0 ; i < lisFilhos.getLength(); i++ ) 
			{
				noFilho = lisFilhos.item(i);
				switch (noFilho.getNodeType())
				{
				case Node.TEXT_NODE:
					paragrafo += noFilho.getNodeValue();
					break;
				case Node.ELEMENT_NODE:
					paragrafo += extraiTexto(noFilho);
					break;
				}
			}
		}

		return paragrafo;
	}
	
	private boolean trataSent(Node elem, int tipo, int nivel)
	{
		Node noFilho;
		String str, nomeNo;
		NodeList lstNodes;
		RegParteTexto novo;
		
		/*
		 *  Verifica se o elemento p ou hn tem algum filho
		 */
		lstNodes = elem.getChildNodes();
		if ( lstNodes != null && lstNodes.getLength() > 0 ) 
		{
			/*
			 *  Percorre os filhos de p ou hn, estou interessado em sent
			 */
			for( int i = 0 ; i < lstNodes.getLength(); i++ ) 
			{
				noFilho = lstNodes.item(i);
				if ( noFilho.getNodeType() == Node.ELEMENT_NODE )
				{
					nomeNo = noFilho.getNodeName();
					if ( nomeNo.equals("sent"))
					{
						Element e = (Element)noFilho;
						
						/*
						 * Estamos assumindo que somente sent terÃ¡ id
						 */
						str = e.getAttribute("id");
						novo = new RegParteTexto(tipo, str, nivel, ordem, extraiTexto(noFilho));
						lstSentencas.add(novo);
					}
				}
				else if ( noFilho.getNodeType() == Node.TEXT_NODE )
				{
					novo = new RegParteTexto(tipo, "", nivel, ordem, noFilho.getNodeValue());
					lstSentencas.add(novo);
				}
			}
		}
	
		return true;
	}

	
	private boolean trataLevel(Node elem, int nivel)
	{
		Node noFilho;
		String nomeNo;
		NodeList lstNodes;
		
		GerenteGUI gui = GerenteGUI.instancia(); 
		/*
		 *  Verifica se o level tem algum filho
		 */
		lstNodes = elem.getChildNodes();
		if ( lstNodes != null && lstNodes.getLength() > 0 ) 
		{
			/*
			 *  Percorre os filhos de level, estou interessado em level, p e hn
			 */
			for( int i = 0 ; i < lstNodes.getLength(); i++ ) 
			{
				noFilho = lstNodes.item(i);
				if ( noFilho.getNodeType() == Node.ELEMENT_NODE )
				{
					nomeNo = noFilho.getNodeName();
					if ( nomeNo.length() > 4 && nomeNo.substring(0, 5).equals("level") )
					{
						trataLevel(noFilho, nivel + 1);
					}
					else if ( nivel > 1 )
					{
						String str;
						
						str = "h" + (nivel - 1);
						if ( nomeNo.equals("p"))
						{
							ordem++;
							trataSent(noFilho, RegParteTexto.TXT_PARAG, nivel);
						}
						else if ( nomeNo.equals("hd") || nomeNo.equals(str) )
						{
							ordem++;
							trataSent(noFilho, RegParteTexto.TXT_CABEC, nivel);
						}
						else
						{
							gui.dlgAlerta( "Elemento " + nomeNo + 
												" inesperado no nÃ­vel " + nivel );

							// NÃ£o reconheci a tag mas posso ter p ou sent dentro dela.
							trataLevel(noFilho, nivel);
						}
					}
					else
					{
						if ( nomeNo.equals("doctitle") )
						{
							ordem++;
							trataSent(noFilho, RegParteTexto.TXT_CABEC, nivel);
						}
						else if ( nomeNo.equals("convertitle") || 
								  nomeNo.equals("docauthor") )
						{
							ordem++;
							trataSent(noFilho, RegParteTexto.TXT_CABEC, nivel + 1);
						}
						else
							gui.dlgAlerta( "Elemento " + nomeNo + 
											    " inesperado no nÃ­vel " + nivel );
						
						// Ã‰ um elemento no primeiro nivel onde sÃ³ deveria haver level
						// para o frontmatter teremos de tratar aqui outras tags
//						return false;
					}
				}
			}
		}
		
		return true;
	}
	
	private boolean montaListaTexto()
	{
		// Obtem o objeto raiz
		Element dtBook;
		NodeList lstMatter;
		boolean saida = false;

		// Aponta para o dom e inicializa o nÃºmero de ordem dos parÃ¡grafos
		ordem = 0;
		dtBook = dom.getDocumentElement();

		// Monta a estrutura com os parÃ¡grafos do frontmatter
		lstMatter = dtBook.getElementsByTagName("frontmatter");
		if ( lstMatter != null && lstMatter.getLength() > 0 )
		{
			saida = trataLevel((Element)lstMatter.item(0), 1);
		}

		// Monta a estrutura com os parÃ¡grafos do bodymatter
		lstMatter = dtBook.getElementsByTagName("bodymatter");
		if ( lstMatter != null && lstMatter.getLength() > 0 )
		{
			saida = trataLevel((Element)lstMatter.item(0), 1);
		}
		
		// Monta a estrutura com os parÃ¡grafos do rearmatter
		lstMatter = dtBook.getElementsByTagName("rearmatter");
		if ( lstMatter != null && lstMatter.getLength() > 0 )
		{
			saida = trataLevel((Element)lstMatter.item(0), 1);
		}
		
		return saida;
	}
}
